home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / AX25SERV.C < prev    next >
C/C++ Source or Header  |  1990-10-06  |  27KB  |  1,041 lines

  1. /* AX25 server code */
  2.  
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. #include "global.h"
  6. #include "config.h"
  7. #include "mbuf.h"
  8. #include "iface.h"
  9. #include "timer.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include "cmdparse.h"
  13. #include "session.h"
  14. #include "slip.h"
  15. #include "tnc2.h"
  16.  
  17. #ifdef AX25
  18. /* "start" and "stop" subcommands */
  19. static int tnc_start(),axdigi_start(),mheard_start(),bridge_start(),
  20.        tnc2_start(),mbox_start();
  21. static struct cmds axstartcmds[] = {
  22.     "bridge",    bridge_start,    0, NULLCHAR,  "cannot start bridge",
  23. #ifdef SMTPC
  24.     "mbox",        mbox_start,    0, NULLCHAR,  "cannot start mbox",
  25. #endif
  26. #ifdef MHEARD
  27.     "mheard",    mheard_start,    0, NULLCHAR,  "cannot start mheard",
  28. #endif
  29.     "netdigi",    axdigi_start,    0, NULLCHAR,  "cannot start netdigi",
  30.     "tnc",        tnc_start,    0, NULLCHAR,  "cannot start tnc",
  31. #ifdef TNC2
  32.     "tnc2",        tnc2_start,    2, "[<dev>=]<iface> ...",
  33.                               "cannot start tnc2",
  34. #endif
  35.     NULLCHAR,    NULLFP,        0,
  36.         "?options", NULLCHAR
  37. };
  38. static int tnc_stop(),axdigi_stop(),mheard_stop(),bridge_stop(),
  39.        tnc2_stop(),mbox_stop();
  40. static struct cmds axstopcmds[] = {
  41.     "bridge",    bridge_stop,    0, NULLCHAR, NULLCHAR,
  42. #ifdef SMTPC
  43.     "mbox",        mbox_stop,    0, NULLCHAR, NULLCHAR,
  44. #endif
  45. #ifdef MHEARD
  46.     "mheard",    mheard_stop,    0, NULLCHAR, NULLCHAR,
  47. #endif
  48.     "netdigi",    axdigi_stop,    0, NULLCHAR, NULLCHAR,
  49.     "tnc",        tnc_stop,    0, NULLCHAR, NULLCHAR,
  50. #ifdef TNC2
  51.     "tnc2",        tnc2_stop,    0, NULLCHAR, "cannot stop tnc2",
  52. #endif
  53.     NULLCHAR,    NULLFP,        0,
  54.         "?options", NULLCHAR
  55. };
  56.  
  57. static void digi_a_state(),digi_b_state(),digi_recv(),digi_send();
  58. static void mheard_state(),mheard_send();
  59. static void bridge_recv(),bridge_state();
  60. void close_ax25(),disc_ax25();
  61.  
  62. extern char nospace[];
  63. extern char *ax25mesgs[];
  64.  
  65. /* start and stop command multiplexers */
  66. doaxstart(argc,argv)
  67. int argc;
  68. char *argv[];
  69. {
  70.     return subcmd(axstartcmds,argc,argv);
  71. }
  72. doaxstop(argc,argv)
  73. int argc;
  74. char *argv[];
  75. {
  76.     return subcmd(axstopcmds,argc,argv);
  77. }
  78.  
  79. /* start an ax25 server */
  80.  
  81. static
  82. ax_sstart (port,r_upcall,t_upcall,s_upcall)
  83. int port;
  84. void (*r_upcall)(),(*t_upcall)(),(*s_upcall)();
  85.  
  86. {
  87.     register struct ax25_call *axp;
  88.     int found = 0;
  89.     void ax_noserv();
  90.  
  91.     for(axp = ax25_port; axp != NULLAXCALL; axp = axp->p_next){
  92.         if(axp->port == port && axp->s_upcall == ax_noserv){
  93.             axp->r_upcall = r_upcall;
  94.             axp->t_upcall = t_upcall;
  95.             axp->s_upcall = s_upcall;
  96.             found++;
  97.         }
  98.     }
  99.  
  100.     if(!found){
  101.         printf("port number %d not found or busy\n",port);
  102.         return 1;
  103.     }
  104.  
  105.     return 0;
  106. }
  107.  
  108. /* stop an ax25 server */
  109.  
  110. static
  111. ax_sstop (port)
  112. int port;
  113.  
  114. {
  115.     register struct ax25_call *axp;
  116.     void ax_noserv();
  117.  
  118.     for (axp = ax25_port; axp != NULLAXCALL; axp = axp->p_next){
  119.         if(axp->port == port){
  120.             axp->r_upcall = axp->t_upcall = NULLVFP;
  121.             axp->s_upcall = ax_noserv;
  122.         }
  123.     }
  124. }
  125.  
  126. char *tnc_conn_msg = NULLCHAR;        /* connect message for TNC */
  127.  
  128. /* Start up tnc server */
  129. static
  130. tnc_start(argc,argv)
  131. int argc;
  132. char *argv[];
  133. {
  134.     void tnc_state();
  135.     char mesg[256];
  136.     int i;
  137.  
  138.     if(argc > 1){            /* set-up a connect message */
  139.         mesg[0] = '\0';
  140.         for(i = 1; i < argc; i++){
  141.         strcat(mesg,argv[i]);
  142.         strcat(mesg,"\r");
  143.         }
  144.         if(tnc_conn_msg != NULLCHAR)
  145.         free(tnc_conn_msg);
  146.         if((tnc_conn_msg = malloc(strlen(mesg)+2)) != NULLCHAR){
  147.         tnc_conn_msg[0] = PID_FIRST|PID_LAST|PID_NO_L3;
  148.         strcpy(tnc_conn_msg + 1,mesg);
  149.         }
  150.     }
  151.     return ax_sstart(TNCPORT,NULLVFP,NULLVFP,tnc_state);
  152. }
  153.  
  154. /* Shut down tnc server */
  155. static
  156. tnc_stop()
  157. {
  158.     return ax_sstop(TNCPORT);
  159. }
  160.  
  161. /* Handle new incoming terminal sessions
  162.  * This is the default state-change upcall function, used when
  163.  * someone else connects to us
  164.  */
  165. void
  166. tnc_state(axp,old,new,msg)
  167. register struct ax25_cb *axp;
  168. int old,new,msg;
  169.  
  170. {
  171.     struct session *s;
  172.     char remote[100];
  173.     long tloc;
  174.     void ax_rx(),ax_tx(),ax_state();
  175.     int ax_parse();
  176.  
  177.     if(new != CONNECTED || msg != LAPBCONN) /* only interested in new connections */
  178.         return;
  179.     if((s = newsession()) == NULLSESSION){
  180.         /* Out of sessions, send DM */
  181.         axp->state = DISCONNECTED;
  182.         return;
  183.     }
  184.     pax25(remote,&axp->addr.dest);
  185.     if ((s->name = malloc((int16)strlen(remote)+1)) == NULLCHAR){
  186.         freesession(s);
  187.         axp->state = DISCONNECTED;
  188.         return;
  189.     }
  190.     s->type = AX25TNC;
  191.     s->cb.ax25_cb = axp;
  192.     s->parse = ax_parse;
  193.     strcpy(s->name,remote);
  194.     stop_timer(&axp->t4);        /* no T4 disconnects on TNC links */
  195.     axp->t4.start = 0;
  196.     axp->r_upcall = ax_rx;
  197.     axp->t_upcall = ax_tx;
  198.     axp->s_upcall = ax_state;
  199.     axp->user = (char *)s;
  200.     pdax25(remote,&axp->addr);    /* add digipeaters */
  201.     time(&tloc);
  202.     printf("\007%.15s Incoming AX25 session %lu from %s(%s)\n",
  203.         ctime(&tloc) + 4,(long) (s - sessions),remote,axp->interface->name);
  204.     fflush(stdout);
  205.     log_ax(axp,"Incoming AX25 session");
  206.     if(tnc_conn_msg != NULLCHAR)        /* a connect message defined? */
  207.         enqueue(&axp->txq,qstring(tnc_conn_msg));
  208. }
  209.  
  210. /* Start up netdigi server */
  211. static
  212. axdigi_start(argc,argv)
  213. int argc;
  214. char *argv[];
  215. {
  216.     return ax_sstart(NETDIGIPORT,NULLVFP,NULLVFP,digi_a_state);
  217. }
  218.  
  219. /* Shut down netdigi server */
  220. static
  221. axdigi_stop()
  222. {
  223.     return ax_sstop(NETDIGIPORT);
  224. }
  225.  
  226. static void
  227. digi_a_state(axp,old,new,msg)
  228. register struct ax25_cb *axp;
  229. int old,new,msg;
  230.  
  231. {
  232.     register struct ax25_cb *axpb;
  233.     register int i,j;
  234.     struct ax25_cb *find_ax25(),*cr_ax25();
  235.     struct ax25_call *axport;
  236.     struct ax25_addr usecall;
  237.     struct ax25 addr;
  238.     char mesg[128],tmp[10];
  239.     extern int16 t1init,t2init;
  240.  
  241.     axpb = find_ax25(&axp->addr.source,&axp->addr.dest);
  242.     switch (new)
  243.     {
  244.     case CONNECTED:
  245.         if(old != DISCONNECTED || msg != LAPBCONN)/* not a new connection? */
  246.         return;                /* ignore state change */
  247.  
  248.         if(axpb != NULLAX25) {        /* connection already exists */
  249.         axp->state = DISCONNECTED;
  250.         return;
  251.         }
  252.  
  253.         /* New connection via NetDigi, setup response and 2nd link */
  254.         pax25(tmp,&((struct ax25_call *) axp->user)->addr);
  255.         sprintf(mesg,"%cNetDigi %s: Please wait for connection.\r",
  256.              PID_FIRST|PID_LAST|PID_NO_L3,tmp);
  257.         /* must not call send_ax25 because it would send out the
  258.            message even before the UA was transmitted */
  259.         enqueue(&axp->txq,qstring(mesg));
  260.  
  261.         ASSIGN(usecall,((struct ax25_call *) axp->user)->addr);
  262.         for (axport = ax25_port; axport != NULLAXCALL; axport = axport->p_next){
  263.         if(axport->port == NETDIGIPORT &&
  264.            axport->interface == axp->interface){
  265.             ASSIGN(usecall,axport->addr);
  266.         }
  267.         }
  268.         usecall.ssid &= ~E;
  269.  
  270.         /* Swap source and destination, reverse digi string */
  271.         ASSIGN(addr.source,axp->addr.dest);
  272.         ASSIGN(addr.dest,axp->addr.source);
  273.  
  274.         /* Construct reverse digipeater path */
  275.         for(i=axp->addr.ndigis-1,j=0;i >= 0;i--,j++){
  276.         ASSIGN(addr.digis[j],axp->addr.digis[i]);
  277.         addr.digis[j].ssid &= ~(E|REPEATED);
  278.         }
  279.         addr.ndigis = axp->addr.ndigis;
  280.         /* set all repeated flags up to my callsign */
  281.         for(i=axp->addr.ndigis-1;i >= 0; i--){
  282.         if(addreq(&addr.digis[i],&((struct ax25_call *) axp->user)->addr)){
  283.             /* found my call, replace it by port call for input iface */
  284.             ASSIGN(addr.digis[i],usecall);
  285.             j = i;    /* for timer values calc */
  286.             while (i >= 0)
  287.             addr.digis[i--].ssid |= REPEATED;
  288.         }
  289.         }
  290.         /* create controlblock, but do not yet open connection */
  291.         if((axpb = cr_ax25(&addr.dest,&addr.source)) != NULLAX25){
  292.         ASSIGN(axpb->addr,addr);
  293.         /* compute timer values depending on real digipeaters */
  294.         axpb->t1.start = t1init * (addr.ndigis - j);
  295.         axpb->t2.start = t2init * (addr.ndigis - j);
  296.         axpb->window = axp->window = axp->maxframe * axp->paclen;
  297.         axpb->r_upcall = axp->r_upcall = digi_recv;
  298.         axpb->t_upcall = axp->t_upcall = digi_send;
  299.         axpb->s_upcall = digi_b_state;
  300.         if(((struct ax25_call *) axp->user)->interface != NULLIF)
  301.             axpb->interface = ((struct ax25_call *) axp->user)->interface;
  302.         else
  303.             axpb->interface = axp->interface;
  304.         lapbstate(axpb,SETUP,LAPBNOMS); /* leave it in SETUP state */
  305.  
  306.         if(axp->interface == axpb->interface) /* both on same band? */
  307.             axp->t2.start = axpb->t2.start = 0; /* disable T2 for